# coding:utf8
import copy
import requests
import re
from fake_useragent import UserAgent

ua = UserAgent()
CHARSET = 'gb2312'
HTTP_URL_RE = re.compile(r'^&random&$')

"""
ASCII及其扩展字符集
作用：表语英语及西欧语言。
位数：ASCII是用7位表示的，能表示128个字符；其扩展使用8位表示，表示256个字符。
范围：ASCII从00到7F，扩展从00到FF。
ISO-8859-1字符集
作用：扩展ASCII，表示西欧、希腊语等。
位数：8位，
范围：从00到FF，兼容ASCII字符集。
GB2312字符集
作用：国家简体中文字符集，兼容ASCII。
位数：使用2个字节表示，能表示7445个符号，包括6763个汉字，几乎覆盖所有高频率汉字。
范围：高字节从A1到F7, 低字节从A1到FE。将高字节和低字节分别加上0XA0即可得到编码。
BIG5字符集
作用：统一繁体字编码。
位数：使用2个字节表示，表示13053个汉字。
范围：高字节从A1到F9，低字节从40到7E，A1到FE。
GBK字符集
作用：它是GB2312的扩展，加入对繁体字的支持，兼容GB2312。
位数：使用2个字节表示，可表示21886个字符。
范围：高字节从81到FE，低字节从40到FE。
GB18030字符集
作用：它解决了中文、日文、朝鲜语等的编码，兼容GBK。
位数：它采用变字节表示(1 ASCII，2，4字节)。可表示27484个文字。
范围：1字节从00到7F; 2字节高字节从81到FE，低字节从40到7E和80到FE；4字节第一三字节从81到FE，第二四字节从30到39。
UCS字符集
作用：国际标准 ISO 10646 定义了通用字符集 (Universal Character Set)。它是与UNICODE同类的组织，UCS-2和UNICODE兼容。
位数：它有UCS-2和UCS-4两种格式，分别是2字节和4字节。
范围：目前，UCS-4只是在UCS-2前面加了0×0000。
UNICODE字符集
作用：为世界650种语言进行统一编码，兼容ISO-8859-1。
位数：UNICODE字符集有多个编码方式，分别是UTF-8，UTF-16和UTF-32。
"""

class HtmlDownloader(object):
    def __init__(self, html_down_conf):
        self._down_conf = html_down_conf
        self.html_down_conf = copy.deepcopy(self._down_conf)

    def download(self, url):
        self.html_down_conf = copy.deepcopy(self._down_conf)
        if url is None:
            return None
        if HTTP_URL_RE.match(self.html_down_conf['user_agent']):
            # 生成随机User-Agent
            headers = {"User-Agent": ua.random}
        if self.html_down_conf.get('add_header'):
            headers.update(self.html_down_conf['add_header'])
        response = requests.get(url, headers=headers)
        if response.status_code != 200:
            return None
        # response_content = response.content
        response_text = response.text
        page_encode_re = re.search(r'charset="(.*?)"', response_text, re.M | re.I)
        page_encode = page_encode_re.group(1)
        # 循环判断各种编码类型, 解决中文乱码的问题
        for k, v in [('utf', 'utf-8'), ('gb', 'GB18030'), ('big', 'BIG5')]:
            if str(page_encode.lower()).find(k) != -1:
                # 如果解码错误就忽略无法解码的字符
                try:
                    response_text_decode = response_text.encode("latin1").decode(v)
                except Exception as e:
                    response_text_decode = response_text.encode("latin1").decode(v, 'ignore')
                    print(e)
                break
        else:
            raise Exception('charset error')
        if not response_text_decode:
            return response_text
        return response_text_decode


